using DA.AnimGraph;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Unity.Mathematics;
using UnityEngine.UIElements;

namespace DA.AnimGraph.Editor {

    [NodeMenuItem(typeof(AGANode_Select), "Select")]
    internal class NodeView_Select : NodeViewBase {

        public override string titleText => "Select";
        protected override NodeViewInspectorSourceBase dataSource => inspectorData;
        NodeViewInspector_Select inspectorData;

        internal override void Init(AGAHandle_Node handle, AnimGraphView graphView, AGEEnvironment ageContext) {
            inspectorData = new NodeViewInspector_Select();
            inspectorData.SetHandle(handle);
            base.Init(handle, graphView, ageContext);
        }
    }

    internal class NodeViewInspector_Select : NodeViewInspectorSourceBase {
        [InspectorField] public AGAFieldModel_IntLink select;
        [InspectorField(label: "过渡时间")] public RefField<float> defaultTransitionDuration;
        [InspectorField(label: "使用输入映射")] public RefField<bool> useInputMapping;

        [InspectorField(tag: "inputPort", isList: true)]
        public List<AGAFieldModel_InputPort> inputPort;
        public List<RefField<int>> inputMapping;
        //[InspectorField(isList: true)] public List<AGAFieldModel_Transition> transitions;


        protected override void LoadFromModel() {
            var model = handleKeeper.handle.data.modelProperty as AGANodeModel_Select;
            select = model.select;
            defaultTransitionDuration = new RefField<float>(model.defaultTransitionDuration);
            //transitions = model.transitions;

            // inputPort
            var bNode = handleKeeper.handle.data as AGANode_BlendBase;
            int childrenCount = bNode.inputChildren.Count;
            inputPort = new List<AGAFieldModel_InputPort>(childrenCount);
            for (int i = 0; i < childrenCount; i++) {
                inputPort.Add(new AGAFieldModel_InputPort(bNode.inputNames[i], bNode.inputChildren[i]));
            }

            // 映射
            inputMapping = new List<RefField<int>>(childrenCount);
            if (model.inputMapping == null) model.inputMapping = new(); // 因为是后加的字段，需要new
            useInputMapping = new RefField<bool>(model.inputMapping.useMapping);
            for (int i = 0; i < childrenCount; i++) {
                // 查找当前port对应的映射，不存在就当做自己映射自己
                int2 r;
                int index = model.inputMapping.mapping.FindIndex(p => p.y == i);
                if (index != -1) {
                    r = model.inputMapping.mapping[index];
                } else {
                    r = new int2(i, i);
                }
                inputMapping.Add(new RefField<int>(r.x));
            }
        }
        protected override void SaveToModel() {
            handleKeeper.handle.ModifyModel(m => {
                var model = m as AGANodeModel_Select;
                model.defaultTransitionDuration = defaultTransitionDuration.value;
                // 映射
                model.inputMapping.useMapping = useInputMapping.value;
                var tmpMapping = new List<int2>();
                for (int i = 0; i < inputMapping.Count; i++) {
                    // if (i == inputMapping[i].value) continue;
                    tmpMapping.Add(new int2(inputMapping[i].value, i));
                }
                model.inputMapping.mapping = tmpMapping;
            });

            // 全量覆盖保存输入端口
            var newInputs = inputPort.Select(m => (m.portUuid, m.name)).ToList();
            handleKeeper.handle.WriteAllInput(newInputs);

            // 如果 useInputMapping 变动了需要刷新 inputPort
            var listView = inspectorWidgets["inputPort"] as ListViewAGE;
            listView.Rebuild();
        }

        protected override VisualElement CustomizeField(string name, InspectorFieldAttribute fieldAttribute, FieldInfo fieldInfo, AGEContext ageContext, Action inspectorChangeCallback) {
            if (fieldAttribute.tag == "inputPort") {
                return BuildInputPortList(name, fieldAttribute, fieldInfo, ageContext, inspectorChangeCallback);
            }
            return base.CustomizeField(name, fieldAttribute, fieldInfo, ageContext, inspectorChangeCallback);
        }
        VisualElement BuildInputPortList(string name, InspectorFieldAttribute fieldAttribute, FieldInfo fieldInfo, AGEContext ageContext, Action inspectorChangeCallback) {
            var listView = new ListViewAGE() {
                title = name,
                enableCountController = true,
                itemsSource = inputPort,
            };

            listView.makeItem = () => {
                var w = new FoldoutWrapper();
                w.upButtonClicked += (index) => {
                    (inputPort[index], inputPort[index - 1]) = (inputPort[index - 1], inputPort[index]);
                    (inputMapping[index], inputMapping[index - 1]) = (inputMapping[index - 1], inputMapping[index]);
                    inspectorChangeCallback?.Invoke(); // 这里已经执行了 listView.Rebuild()
                };
                w.downButtonClicked += (index) => {
                    (inputPort[index], inputPort[index + 1]) = (inputPort[index + 1], inputPort[index]);
                    (inputMapping[index], inputMapping[index + 1]) = (inputMapping[index + 1], inputMapping[index]);
                    inspectorChangeCallback?.Invoke(); // 这里已经执行了 listView.Rebuild()
                };
                w.deleteButtonClicked += (index) => {
                    inputMapping.RemoveAt(index);
                    inputPort.RemoveAt(index);
                    inspectorChangeCallback?.Invoke(); // 这里已经执行了 listView.Rebuild()
                };
                var l = new InspectorField_SelectPort();
                return (l, w);
            };

            listView.bindItem = (element, wrapper, index) => {
                VisualElement nameInputField = null;
                if (element is InspectorField_SelectPort field) {
                    field.portField.Init(null, inputPort[index], ageContext, inspectorChangeCallback);
                    nameInputField = field.portField;
                    field.EnableInputMapping(useInputMapping.value);
                    if (useInputMapping.value) {
                        field.mapping.Init("mapping", inputMapping[index], ageContext, inspectorChangeCallback);
                    }
                }
                if (wrapper is FoldoutWrapper w) {
                    w.index = index;
                    w.text = $"[{index}]";
                    w.enableUp = index > 0;
                    w.enableDown = index < inputPort.Count - 1;
                    w.enableDelete = inputPort.Count > 2;
                    w.SetToTitle(nameInputField);
                }
            };

            listView.addButtonClicked = () => {
                inputPort.Add(new AGAFieldModel_InputPort("new port"));
                inputMapping.Add(new RefField<int>(inputMapping.Count));
                inspectorChangeCallback?.Invoke(); // 这里已经执行了 listView.Rebuild()
            };

            return listView;
        }

        class InspectorField_SelectPort : VisualElement {

            public InspectorField_InputPort portField; // 这部分不再显示在foldout下，而是在标题上，这里只是持有对象而不添加到显示
            public InspectorField_Int mapping;

            public InspectorField_SelectPort() {
                portField = new() {
                    name = "name-field",
                    style = { flexGrow = 1, }
                };
            }

            public void EnableInputMapping(bool enable) {
                if ((mapping != null) == enable) {
                    return;
                }
                if (enable) {
                    mapping = new();
                    Add(mapping);
                } else {
                    Remove(mapping);
                    mapping = null;
                }
            }

        }

    }
}
